home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / pctecap.arc / METHOD1.ASM < prev    next >
Assembly Source File  |  1986-03-15  |  14KB  |  327 lines

  1.         PAGE    ,132
  2.         TITLE     Method 1
  3.         .286C     ; Tell MASM 2.0 about 286 instructions
  4. ;--------------------------------------------------------------:
  5. ;       Sample Program 1                                       :
  6. ;                                                              :
  7. ; This program switches into Protected Virtual Mode, changes   :
  8. ; the display attribute to reverse video, and returns to Real  :
  9. ; Mode to exit to DOS                                          :
  10. ;                                                              :
  11. ; Once entered into a file, do the following:                  :
  12. ;       MASM SAMPLE1;                                          :
  13. ;       LINK SAMPLE1;                                          :
  14. ;       EXE2BIN SAMPLE1 SAMPLE1.COM                            :
  15. ;       DEL SAMPLE1.EXE                                        :
  16. ;                                                              :
  17. ; WARNING: This program will "kill" a PC.  I should only       :
  18. ; be run on an AT.                                             :
  19. ;--------------------------------------------------------------:
  20.  
  21. bios_data_seg SEGMENT at 0040h
  22.               ORG    0067h
  23. io_rom_init   dw ?        ; dword variable in BIOS data segment
  24. io_rom_seg    dw ?        ;  used to store a dword address
  25. bios_data_seg ENDS
  26.  
  27. descriptor    STRUC
  28. seg_limit     dw 0        ; segment limit (1-65536 bytes)
  29. base_lo_word  dw 0        ; 24 bit physical address
  30. base_hi_byte  db 0        ; (0 - (16M-1))
  31. access_rights db 0        ; access rights byte
  32.               dw 0        ; reserved_386
  33. descriptor    ENDS
  34.  
  35. cmos_port       equ 070h
  36. code_seg_access equ 10011011b ;access rights byte for code seg
  37. data_seg_access equ 10010011b ;access rights byte for data seg
  38. disable_bit20   equ 11011101b ;8042 function code to de-gate A20
  39. enable_bit20    equ 11011111b ;8042 function code to gate A20
  40. inta01          equ 021h      ;8259 Int Controller #1
  41. intb01          equ 0A1h      ;8259 Int Controller #2
  42. port_a          equ 060h      ;8042 port A
  43. shut_cmd        equ 0FEh      ;cmd to 8042: shut down AT
  44. shut_down       equ 00Fh      ;CMOS shut down byte index
  45. status_port     equ 064h      ;8042 status port
  46. virtual_enable  equ 0001h     ;LSB=1: Protected Virtual Mode
  47.  
  48.         SUBTTL  Macro Definitions
  49.         PAGE
  50. ;--------------------------------------------------------------:
  51. ; These mnemonics are not supported in MASM 2.0 therefore      :
  52. ; they are supplied here as MACROS.                            :
  53. ;--------------------------------------------------------------:
  54. lgdt    MACRO      lgdt1      ;; Load Global Descriptor Table
  55.         LOCAL      lgdt2,lgdt3
  56.         db         00Fh
  57. lgdt2   label      byte
  58.         mov        dx,word ptr lgdt1
  59. lgdt3   label      byte
  60.         org        offset lgdt2
  61.         db         001h
  62.         org        offset lgdt3
  63.         ENDM
  64.  
  65. lmsw    MACRO      lmsw1      ;; Load Machine Status Word
  66.         LOCAL      lmsw2,lmsw3
  67.         db         00Fh
  68. lmsw2   label      byte
  69.         mov        si,ax
  70. lmsw3   label      byte
  71.         org        offset lmsw2
  72.         db         001h
  73.         org        offset lmsw3
  74.         ENDM
  75.  
  76.                               ;; This is a "hard coded" far jump
  77. jumpfar MACRO      jumpfar1,jumpfar2
  78.         db         0EAh
  79.         dw         (offset jumpfar1)
  80.         dw         jumpfar2
  81.         ENDM
  82.  
  83.         SUBTTL     Program entry point and data area
  84.         PAGE
  85. cseg    SEGMENT para       public        'code'
  86.         ASSUME  cs:cseg
  87.  
  88.         ORG     100h
  89. start:  jmp     short     main
  90.  
  91.         EVEN
  92. gdt     LABEL   word
  93.  
  94. gdt_desc    EQU  (($-gdt)/8)*8 + 0000000000000000b
  95. gdt1        descriptor  <gdt_leng,,,data_seg_access,>
  96. cs_code     EQU  (($-gdt)/8)*8 + 0000000000000000b
  97. gdt2        descriptor  <cseg_leng,,,code_seg_access,>
  98. cs_data     EQU  (($-gdt)/8)*8 + 0000000000000000b
  99. gdt3        descriptor  <cseg_leng,,,data_seg_access,>
  100. ss_desc     EQU  (($-gdt)/8)*8 + 0000000000000000b
  101. gdt4        descriptor  <0FFFFh,,,data_seg_access,>
  102. ds_desc     equ  (($-gdt)/8)*8 + 0000000000000000b
  103. gdt5        descriptor  <0FFFFh,,,data_seg_access,>
  104. es_desc     equ  (($-gdt)/8)*8 + 0000000000000000b
  105. gdt6        descriptor  <0FFFFh,,,data_seg_access,>
  106. gdt_leng    EQU  $-gdt
  107.             PAGE
  108. ;--------------------------------------------------------------:
  109. ; Format of the Segment Selector Component:                    :
  110. ;                                                              :
  111. ; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+            :
  112. ; |       INDEX                          +TI+ RPL +            :
  113. ; +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+            :
  114. ;                                                              :
  115. ; TI = Table Indicator (0=GDT, 1=LDT)                          :
  116. ; RPL = Requested Privelege Level (00 = highest; 11 = Lowest)  :
  117. ;--------------------------------------------------------------:
  118. ; Format of the Global Descriptor Table                        :
  119. ;                       .-----------+                +---> TI  :
  120. ;                       V           |                |++-> RPL :
  121. ;       GDT ==> +---------------+   |                |||       :
  122. ;               |   GDT_DESC    | --+   0000000000000000b      :
  123. ;               +---------------+                              :
  124. ;               |    CS_CODE    |       0000000000001000b      :
  125. ;               +---------------+                              :
  126. ;               |    CS_DATA    |       0000000000010000b      :
  127. ;               +---------------+                              :
  128. ;               |    SS_DESC    |       0000000000011000b      :
  129. ;               +---------------+                              :
  130. ;               |    DS_DESC    |       0000000000100000b      :
  131. ;               +---------------+                              :
  132. ;               |    ES_DESC    |       0000000000101000b      :
  133. ;               +---------------+                              :
  134. ;--------------------------------------------------------------:
  135.  
  136. i8259_1 db       ?         ; store for status of 8259 #1
  137. i8259_2 db       ?         ; store for status of 8259 #2
  138.  
  139.         SUBTTL Program Main
  140.         PAGE
  141. ;--------------------------------------------------------------:
  142. ; MAIN                                                         :
  143. ;--------------------------------------------------------------:
  144.         ASSUME   ds:cseg
  145. main    PROC                       ;ES=DS=CS
  146.         cld                        ;forward
  147.  
  148.         mov      dx,cs             ;form 24bit address out of
  149.         mov      cx,offset gdt     ; CS:GDT
  150.         call     form_24bit_address
  151.         mov      gdt1.base_lo_word,dx  ;DESC now points to gdt
  152.         mov      gdt1.base_hi_byte,cl
  153.  
  154.         mov      dx,cs             ;form 24bit address out of
  155.         xor      cx,cx             ;  CS:0000
  156.         call     form_24bit_address
  157.         mov      gdt2.base_lo_word,dx  ;CS_CODE now points to
  158.         mov      gdt2.base_hi_byte,cl  ; CSEG as a code segment
  159.         mov      gdt3.base_lo_word,dx  ;CS_DATA now points to
  160.         mov      gdt3.base_hi_byte,cl  ; CSEG as a data segment
  161.  
  162.         mov      dx,ss             ;form 24bit address out of
  163.         xor      cx,cx             ; SS:0000
  164.         call     form_24bit_address
  165.         mov      gdt4.base_lo_word,dx  ;SS_DESC now points to
  166.         mov      gdt4.base_hi_byte,cl  ; stack segment
  167.  
  168.         lgdt     gdt               ;Load the GDTR
  169.  
  170.         mov      ah,enable_bit20   ;gate address bit 20 on
  171.         call     gate_a20
  172.         or       al,al             ; was the command accepted?
  173.         jz       m_10              ; go if yes
  174.         mov      dx,offset gate_failure  ;print error msg
  175.         mov      ah,9                    ; and terminate
  176.         int      21h
  177.         int      20h
  178.  
  179. gate_failure     db   "Address line A20 failed to Gate open$"
  180.  
  181. m_10:   cli                  ;No interrupts
  182.  
  183.         in       al,inta01   ;get status of Int Controller #1
  184.         mov      i8259_1,al
  185.         in       al,intb01   ;get status of Int Controller #2
  186.         mov      i8259_2,al
  187.  
  188.         ASSUME   ds:bios_data_seg
  189.         mov      dx,bios_data_seg  ;Real Mode Return address
  190.         mov      ds,dx
  191.         mov      io_rom_seg,cs
  192.         mov      io_rom_init,offset real
  193.  
  194.         mov      al,shut_down      ;Set shutdown byte
  195.         out      cmos_port,al      ; to shut down x05.
  196.         jmp      short  $+2        ;I/O delay
  197.         mov      al,5
  198.         out      cmos_port+1,al
  199.  
  200.         mov      ax,virtual_enable ;machine status word needed to
  201.         lmsw     ax                ;switch to virtual mode
  202.         jumpfar m_20,cs_code       ;Must purge prefetch queue
  203.  
  204. m_20:   ASSUME   ds:cseg       ;IN VIRTUAL MODE ...
  205.         mov      ax,ss_desc    ;stack segment selector
  206.         mov      ss,ax         ;user's ss+sp is not a descriptor
  207.  
  208.         mov      ax,cs_data
  209.         mov      ds,ax         ;DS = CSEG as data
  210.  
  211.         mov      gdt5.base_lo_word,0000h  ;use 8000 for COLOR
  212.         mov      gdt5.base_hi_byte,0Bh
  213.         mov      gdt6.base_lo_word,0000h
  214.         mov      gdt6.base_hi_byte,0Bh
  215.  
  216.         mov      ax,ds_desc
  217.         mov      ds,ax
  218.         mov      ax,es_desc
  219.         mov      es,ax
  220.         mov      cx,80*25
  221.         xor      si,si
  222.         xor      di,di
  223. m_30:   lodsw
  224.         mov      ah,70h         ;attribute reverse video
  225.         stosw
  226.         loop     m_30
  227.  
  228.         mov      al,shut_cmd    ;shutdown cmd
  229.         out      status_port,al ;get back into REAL mode
  230. m_40:   hlt
  231.         jmp      short m_40
  232.  
  233.         SUBTTL   Gate A20
  234.         PAGE
  235. ;--------------------------------------------------------------:
  236. ; GATE_A20                                                     :
  237. ; This routine controls a signal which gates address bit 20.   :
  238. ; The gate A20 signal is an output of the 8042 slave processor.:
  239. ; Address bit 20 should be gated on before entering protected  :
  240. ; mode.  It should be gated off after entering real mode from  :
  241. ; protected mode.                                              :
  242. ; Input:  (AH)=0DDh addr bit 20 gated off (A20 always 0)       :
  243. ;         (AH)=0DFh addr bit 20 gated on  (286 controls A20)   :
  244. ; Output: (AL)=0 operation successful.  8042 has accepted cmd  :
  245. ;         (AL)=2 Failure -- 8042 unable to accept command.     :
  246. ;--------------------------------------------------------------:
  247. gate_a20  PROC
  248.         cli                  ;disable ints while using 8042
  249.         call   empty_8042    ;insure 8042 input buffer empty
  250.         jnz    gate_a20_01   ;ret if 8042 unable to accept cmd
  251.         mov    al,0D1h       ;8042 command to write output port
  252.         out    status_port,al  ;output cmd to 8042
  253.         call   empty_8042      ;wait for 8042 to accept command
  254.         jnz    gate_a20_01   ;ret if 8042 unable to accept cmd
  255.         mov    al,ah         ;8042 port data
  256.         out    port_a,al     ;output port data to 8042
  257.         call   empty_8042    ;wait for 8042 to port data
  258. gate_a20_01:
  259.         ret
  260. gate_a20  ENDP
  261. ;--------------------------------------------------------------:
  262. ; EMPTY_8042                                                   :
  263. ; This routine waits for the 8042 buffer to empty              :
  264. ; Input:  None                                                 :
  265. ; Output: (AL)=0 8042 input buffer empty (ZF=1)                :
  266. ;         (AL)=2 Time out, 8042 buffer full (ZF=0)             :
  267. ;--------------------------------------------------------------:
  268. empty_8042  PROC
  269.         push   cx             ;save CX
  270.         sub    cx,cx          ;CX=0 will be the time out value
  271. empty_8042_01:
  272.         in     al,status_port ;read 8042 status port
  273.         and    al,00000010b   ;test input buffer full flag (D1)
  274.         loopnz empty_8042_01  ;loop until input buffer empty
  275.                               ; or time out
  276.         pop    cx             ;restore CX
  277.         ret
  278. empty_8042  ENDP
  279.  
  280.         SUBTTL form_24bit_address
  281.         PAGE
  282. ;--------------------------------------------------------------:
  283. ; FORM_24BIT_ADDRESS                                           :
  284. ;    Input:  DX has some segment                               :
  285. ;            CX has some offset                                :
  286. ;    Output: DX has base_lo_word                               :
  287. ;            CL has base_hi_byte                               :
  288. ;--------------------------------------------------------------:
  289. form_24bit_address  PROC
  290.         push   ax
  291.              ;DX == s15 s14 s13 s12 s11 ... s04 s03 s02 s01 s00
  292.         rol    dx,4    
  293.              ;DX == s11 ... s04 s03 s02 s01 s00 s15 s14 s13 s12
  294.         mov    ax,dx
  295.              ;AX == s11 ... s04 s03 s02 s01 s00 s15 s14 s13 s12
  296.         and    dl,0F0h
  297.              ;DX == s11 ... s04 s03 s02 s01 s00   0   0   0   0
  298.         and    ax,0Fh
  299.              ;AX ==   0 ...   0   0   0   0   0 s15 s14 s13 s12
  300.         add    dx,cx   ;form_24bit_address
  301.         mov    cx,ax   ;get base_hi_byte in CL
  302.         adc    cl,ch   ;carry in (CH=0)
  303.         pop    ax
  304.         ret
  305. form_24bit_address ENDP
  306.  
  307.         SUBTTL     Real Mode re-entry point.
  308.         PAGE
  309.         ASSUME ds:cseg             ;IN REAL MODE ...
  310.  
  311. real:   mov    dx,cs
  312.         mov    ds,dx               ;DS = CS
  313.         mov    ah,disable_bit20    ;gate address bit 20 on
  314.         call   gate_a20
  315.         mov    al,i8259_1
  316.         out    inta01,al       ;set status of Int Controller #1
  317.         mov    al,i8259_2
  318.         out    intb01,al       ;set status of Int Controller #2
  319.  
  320.         sti                    ;turn the interrupts on
  321.         int    20h             ;back to DOS
  322.  
  323. main       ENDP
  324. cseg_leng  EQU $
  325. cseg       ENDS
  326.            END  start
  327.